#include "func.h"
#include "Message.hpp"
#include <unistd.h>
#include <iostream>
#include <crypt.h>
using std::cin;
using std::cout;
using std::endl;


int main()
{
    //1.socket
    int clientfd = socket(AF_INET,SOCK_STREAM,0);
    if(clientfd < 0){
        perror("socket");
        return EXIT_FAILURE;
    }

    //2.connect
    struct sockaddr_in serveraddr;
    memset(&serveraddr,0,sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(12345);
    serveraddr.sin_addr.s_addr = inet_addr("192.168.189.128");
    int ret = connect(clientfd,(const struct sockaddr*)&serveraddr,sizeof(serveraddr));
    if(ret < 0){
        perror("connect");
        close(clientfd);
        return EXIT_FAILURE;
    }
    printf("connect success\n,login for 1, register for 2: \n");


    fd_set readfds;
    FD_ZERO(&readfds);
    FD_SET(clientfd, &readfds); 
    FD_SET(STDIN_FILENO, &readfds); 
    int max_fd = clientfd;
    char buf[1024] = {0};
    
    wd::TLV tlv;


    int flag = 0;
    cin>>flag;
    if(flag == 1){
        tlv.type = wd::TASK_LOGIN_SECTION1; 
    }else if(flag == 2){
        tlv.type = wd::TASK_REGISTER_SECTION1;
    }else{
        printf("error\n"); 
        return -1;
    }

    //请用户输入用户名：
    printf("请输入用户名：\n");
    memset(buf,0,sizeof(buf));
    ret = read(STDIN_FILENO,buf,sizeof(buf));

    tlv.length = ret;
    strncpy(tlv.data,buf,ret);
    ret = send(clientfd, &tlv, 8 + tlv.length,0); 
    printf("send %d bytes \n",ret);

    while(1){
        fd_set readyset = readfds;
        ret = select(max_fd+1, &readyset,NULL,NULL,NULL);
        if(ret == -1){
            perror("select");
            continue;
        }

        if(FD_ISSET(clientfd,&readyset)){
            wd::TLV tlv;
            memset(&tlv,0,sizeof(tlv));
            ret = recv(clientfd,&tlv,sizeof(tlv),0);
            if(ret == 0){
                printf("server disconneted.\n");
                close(clientfd);
                break;
            }
            printf("ret : %d\n",ret);
            printf("tlv.type:%d\n",tlv.type);
            printf("tlv.length:%d\n",tlv.length);
            printf("tlv.data: %s \n",tlv.data);
            if(tlv.type == wd::TASK_LOGIN_SECTION1_RESP_OK){
                //说明用户名验证成功,根据盐值生成密文
                //首先让用户输入密码
                char * passwd = getpass("请输入密码：");
                char * encoded = crypt(passwd,tlv.data);
                printf("encoded : %s \n",encoded);

                memset(&tlv,0,sizeof(tlv));
                tlv.type = wd::TASK_LOGIN_SECTION2;
                tlv.length = strlen(encoded);
                strncpy(tlv.data,encoded,tlv.length);
                ret = send(clientfd, &tlv, 8 + tlv.length,0); 
                printf("send %d bytes \n",ret);
            }
            else if(tlv.type == wd::TASK_REGISTER_SECTION1_RESP_OK){
                char * passwd = getpass("请输入密码：");
                //char * passwd2 = getpass("再次输入密码：");
                //if(strcmp(passwd,passwd2) != 0){
                //    printf("密码不一致\n");
                //    return -1;
                //}
                printf("your passwd = %s \n",passwd);
                char * encoded = crypt(passwd,tlv.data);
                printf("encoded :__%s__ ,len: %ld\n",encoded,strlen(encoded));
                memset(&tlv,0,sizeof(tlv));
                tlv.type = wd::TASK_REGISTER_SECTION2;
                tlv.length = strlen(encoded);
                strncpy(tlv.data,encoded,tlv.length);
                ret = send(clientfd, &tlv, 8 + tlv.length,0); 
                printf("send %d bytes \n",ret);
            }
            else if(tlv.type == wd::TASK_LOGIN_SECTION2_RESP_OK){
                printf("密码验证通过，登录成功\n");
            }
            else if(tlv.type == wd::TASK_LOGIN_SECTION2_RESP_ERROR){
                printf("登陆失败失败\n");
            }
            else if(tlv.type == wd::TASK_REGISTER_SECTION2_RESP_ERROR){
                printf("可能出现密码过短 或其他错误,注册失败\n");
            }else if(tlv.type == wd::TASK_REGISTER_SECTION2_RESP_OK){
                printf("注册成功 \n");
            }
        }

    }


    return 0;
}

